package com.etoak.stock.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.etoak.stock.mapper.StockBlockRtInfoMapper;
import com.etoak.stock.mapper.StockMarketIndexInfoMapper;
import com.etoak.stock.mapper.StockRtInfoMapper;
import com.etoak.stock.pojo.domin.*;
import com.etoak.stock.pojo.vo.StockInfoConfig;
import com.etoak.stock.service.StockService;
import com.etoak.stock.utils.DateTimeUtil;
import com.etoak.stock.vo.resp.PageResult;
import com.etoak.stock.vo.resp.R;
import com.etoak.stock.vo.resp.ResponseCode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/*
* 获取国内大盘最新数据
*
* */
@SuppressWarnings("ALL")
@Service
@Slf4j
public class StockServiceImpl implements StockService {
    @Autowired  StockInfoConfig  stockInfoConfig;
    @Autowired
    StockMarketIndexInfoMapper stockMarketIndexInfoMapper;


    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;
    @Autowired
    StockRtInfoMapper stockRtInfoMapper;


    @Autowired
    private Cache<String,Object> caffeineCache;
    @Override
    public R<List<InnerMarketDomain>> getInnerMarketInfo() {
        //从缓存中加载数据，如果不存在，则走补偿策略获取数据，并存入本地缓存
        R<List<InnerMarketDomain>> result= (R<List<InnerMarketDomain>>) caffeineCache.get("innerMarketInfos", key->{
            //如果不存在，则从数据库查询
            //1.获取最新的股票交易时间点
            Date lastDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
            //TODO 伪造数据，后续删除
            //lastDate=DateTime.parse("2024-10-14 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
            //2.获取国内大盘编码集合
            List<String> innerCodes = stockInfoConfig.getInner();
            //3.调用mapper查询
            List<InnerMarketDomain> infos= stockMarketIndexInfoMapper.getMarketInfo(lastDate,innerCodes);
            //4.响应
            return R.ok(infos);
        });
        return result;


    }

    @Override
    public R<List<StockBlockDomain>> getStockBlockInfo() {
        //获当前的最新交易日期
        Date curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        curDateTime=DateTime.parse("2022-01-14 16:57:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //获取数据
        List<StockBlockDomain> data=stockBlockRtInfoMapper.getStockBlockInfo(curDateTime);
        //判断集合的数据是否为空
        if(CollectionUtil.isEmpty(data)){
            return R.error(ResponseCode.NO_RESPONSE_DATA.getMessage());
        }
            return R.ok(data);
    }

    @Override
    public R<PageResult<StockUpdownDomain>> getStockUpdownInfo(Integer page, Integer pageSize) {
        Date curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        curDateTime=DateTime.parse("2024-10-18 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        PageHelper.startPage(page,pageSize);
        List<StockUpdownDomain> pageDate=stockRtInfoMapper.getStockUpdownInfo(curDateTime);
        PageInfo<StockUpdownDomain>  pageInfo=new PageInfo<>(pageDate);
        PageResult<StockUpdownDomain> tPageResult = new PageResult<>(pageInfo);
        return R.ok(tPageResult);
    }

    @Override
    public R<Map<String, List>> getStockUpdownCount() {
        //1.获取最新的交易时间范围 openTime  curTime
        //1.1 获取最新股票交易时间点
        DateTime curDate = DateTimeUtil.getLastDate4Stock(DateTime.now());
        curDate= DateTime.parse("2022-01-06 14:25:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date endDate = curDate.toDate();
        //1.2 获取最新交易时间对应的开盘时间
        Date openDate = DateTimeUtil.getOpenDate(curDate).toDate();
        //2.查询涨停数据
        //约定mapper中flag入参： 1-》涨停数据 0：跌停
        List<Map> upCounts=stockRtInfoMapper.getStockUpdownCounts(openDate,endDate,1);
        //3.查询跌停数据
        List<Map> dwCounts=stockRtInfoMapper.getStockUpdownCounts(openDate,endDate,0);
        //4.组装数据
        Map<String, List> mapInfo = new HashMap<>();
        mapInfo.put("upList",upCounts);
        mapInfo.put("downList",dwCounts);
        //5.返回结果
        return R.ok(mapInfo);
    }

    @Override
    public R<List<StockUpdownDomain>> getStockUpdownLimit() {
        Date curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        curDateTime=DateTime.parse("2021-12-30 09:56:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        List<StockUpdownDomain> date=stockRtInfoMapper.getStockUpdownLimit(curDateTime);
        return R.ok(date);
    }
    /*
     * @author 孙有泽
     * @date 2024/10/23 13:14
     * @description 导出数据excel
     */
    @Override
    public void exportStockDownInfo(Integer page, Integer pageSize, HttpServletResponse response) {
        //获取分页数据
        R<PageResult<StockUpdownDomain>> stockUpdownInfo = this.getStockUpdownInfo(page, pageSize);
        List rows = stockUpdownInfo.getData().getRows();
            //如果集合为空，响应错误提示信息
            /*if (CollectionUtils.isEmpty(rows)) {
                //响应提示信息
                //RequestInfoUtil.setUtf8(response);
                R<Object> r = R.error(ResponseCode.NO_RESPONSE_DATA);
                response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                response.getWriter().write(new ObjectMapper().writeValueAsString(r));
                return;
            }*/
            //2.将数据导出excel中
            //告知浏览器这是excel形式的文件
            response.setContentType("application/vnd.ms-excel");
            //3.设置默认的文件名称
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            response.setCharacterEncoding("utf-8");
            try {
                //设置默认文件名称：兼容一些特殊浏览器
                String encode = URLEncoder.encode("股票信息表", "UTF-8");
                response.setHeader("content-disposition", "attachment;filename="+encode+".xlsx");
                EasyExcel.write(response.getOutputStream(), StockUpdownDomain.class).sheet("摸版").doWrite(rows);
            }catch (Exception e){
                log.info("当前导出数据异常，当前页：{},每页大小：{},异常时间,异常信息：{}",page,pageSize,DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),e.getMessage());
                /*response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                R<Object> error = R.error(ResponseCode.ERROR);
                String s = null;
                try {
                    s = new ObjectMapper().writeValueAsString(error);
                    response.getWriter().write(s);
                } catch (IOException ex) {
                    log.info("响应错误信息失败,异常信息：{}",page,pageSize,DateTime.now().toString("yyyy-MM-dd HH:mm:ss"),ex.getMessage());
                    throw new RuntimeException(ex);
                }*/
            }
            }
/*
 * @author 孙有泽
 * @date 2024/10/23 13:13
 * @description 统计大盘T日和T-1日每分钟交易量的统计
 */
    @Override
    public R<Map<String, List>> getCompareStockTradeAmt() {
       //1.获取T日（最新股票交易日的日期范围）
        //结束时间
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        curDateTime= DateTime.parse("2021-12-29 14:59:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date tEndDate = curDateTime.toDate();
        //开始时间
        Date tStarDate=DateTimeUtil.getOpenDate(curDateTime).toDate();
        //========================================================
        //2.T-1日的时间范围
        //结束时间
        DateTime preTEnDateTime = DateTimeUtil.getPreviousTradingDay(curDateTime);
        preTEnDateTime= DateTime.parse("2021-12-28 14:59:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date tpreEndDate = preTEnDateTime.toDate();
        //开始时间
        Date tPreStarDate = DateTimeUtil.getOpenDate(preTEnDateTime).toDate();
        //3.统计T日
        List<Map> tDate=stockMarketIndexInfoMapper.getSumAmtInfo(tStarDate,tEndDate,stockInfoConfig.getInner());
        //4.统计T-1日
        List<Map> preTDate=stockMarketIndexInfoMapper.getSumAmtInfo(tPreStarDate,tpreEndDate,stockInfoConfig.getInner());
        HashMap<String, List> infos = new HashMap<>();
        infos.put("amtList",tDate);
        infos.put("yesAmtList",preTDate);
        return R.ok(infos);
    }
    /*
     * @author 孙有泽
     * @date 2024/10/24 21:41
     * @description 统计当前时间下（精确到分钟），A股在各个涨跌区间股票的数量；
     */
    @Override
    public R<Map> getIncreaseRangeInfo() {
        //获取当前最新股本的交易时间点
        DateTime curDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        curDateTime=DateTime.parse("2024-10-18 15:00:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date curDate=curDateTime.toDate();
        //通用mapper获取数据
        List<Map> infos=stockRtInfoMapper.getIncreaseRangeInfoByDate(curDate);
        List<String> orderSections = stockInfoConfig.getUpDownRange();
       /* ArrayList<Map> objects = new ArrayList<>();
        for(String title:orderSections){
            Map tmp=null;
            for(Map info:infos){
                if(info.containsValue(title)){
                    tmp=info;
                    break;
                }
            }
            if (tmp == null) {
                tmp=new HashMap();
                tmp.put("count",0);
                tmp.put("title",title);
            }
            objects.add(tmp);
        }*/
        List<Map> collect = orderSections.stream().map(title -> {
            Optional<Map> first = infos.stream().filter(map -> map.containsValue((title))).findFirst();
            if (first.isPresent()) {
                return first.get();
            } else {
                Map tmp = new HashMap();
                tmp.put("count", 0);
                tmp.put("title", title);
                return tmp;
            }
        }).collect(Collectors.toList());
        //组装数据
        HashMap<String, Object> objectObjectHashMap = new HashMap<>();
        objectObjectHashMap.put("time",curDateTime.toString("yyyy-MM-dd HH:mm:ss"));
        objectObjectHashMap.put("infos",collect);
        return R.ok(objectObjectHashMap);
    }
    /*
     * @param StockCode 股票编码
     * @author 孙有泽
     * @date 2024/10/2 21:06
     * @description 查询个股的分时行情数据，也就是统计指定股票T日每分钟的交易数据
     */
    @Override
    public R<List<Stock4MinuteDomain>> getStockScreenTimeSharing(String stockCode) {
        //获取t日最新股票交易时间点 endTime openTime
        DateTime endDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        // endDateTime= DateTime.parse("2021-12-30 09:56:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date endDate=endDateTime.toDate();
        Date openDate=DateTimeUtil.getOpenDate(endDateTime).toDate();
        List<Stock4MinuteDomain> data=stockRtInfoMapper.getStockMinZuteIngfo(openDate,endDate,stockCode);
        return R.ok(data);
    }
    /*
     * @author 孙有泽
     * @date 2024/10/25 14:02
     * @description 单个个股日K 数据查询 ，可以根据时间区间查询数日的K线数据
     */
    @Override
    public R<List<Stock4EvrDayDomain>> getStockScreenDkline(String stockCode) {
        //获取统计日k线的数据的时间范围
        //1.1获取截止时间
        DateTime endDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        endDateTime=DateTime.parse("2024-10-18 15:00:00",DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        Date endDate = endDateTime.toDate();
        //1.2获取开始时间
        Date startDate = endDateTime.minusMonths(3).toDate();
        //调用mapper获取指定日期范围内的日k线的数据
       // List<Stock4EvrDayDomain> getStockDayKline=stockRtInfoMapper.getStockDayKline(startDate,endDate,stockCode);
        //分布
        List<Date> getMaxTime=stockRtInfoMapper.getMaxTime(startDate,endDate,stockCode);
        List<Stock4EvrDayDomain> getStockDayKline=stockRtInfoMapper.getStockDayKline2(stockCode,getMaxTime);
        return  R.ok(getStockDayKline);
    }

}
